package com.joymart.order.service;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.joymart.common.model.Range;
import com.joymart.common.system.IdGenerator;
import com.joymart.common.utils.DatetimeUtils;
import com.joymart.common.utils.SecurityUtils;
import com.joymart.dictionary.DictionaryService;
import com.joymart.order.model.Order;
import com.joymart.order.model.OrderEvent;
import com.joymart.order.repo.OrderEventRepository;
import com.joymart.user.service.UserCacheManager;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

@Service
public class OrderEventService {

    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private UserCacheManager userCacheManager;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private JdbcAggregateTemplate jdbcAggregateTemplate;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderEventRepository orderEventRepository;

    public void logOrderEvent(String type, Order order) {
        String orderId = order.getId();
        String currentUserId = SecurityUtils.getCurrentUserId();
        switch (type) {
            case "CREATED", "CANCELED", "SECOND_SELLER_PAID", "RECEIVED", "FIRST_SELLER_INFORMED",
                 "SECOND_SELLER_INFORMED" -> insertOrderEvent(orderId, type, currentUserId);
            // 确认买家付款， 金额为店铺利润
            case "BUYER_PAID" ->
                    insertOrderEvent(orderId, type, order.getFirstSellerId(), order.getFirstSellerProfit());
            // 确认经营店铺付款， 金额为育成利润
            case "FIRST_SELLER_PAID" ->
                    insertOrderEvent(orderId, type, order.getSecondSellerId(), order.getSecondSellerProfit());
            case "MADE_DELIVERY" ->
                    insertOrderEvent(orderId, type, currentUserId, BigDecimal.ZERO,
                            new JSONObject().put("deliveryVendorId", order.getDeliveryVendorId())
                                            .put("deliveryNo", order.getDeliveryNo()));
            //todo 退款等
        }
    }


    public void insertOrderEvent(String orderId, String type, String userId) {
        this.insertOrderEvent(orderId, type, userId, BigDecimal.ZERO);
    }

    public void insertOrderEvent(String orderId, String type, String userId, BigDecimal amount) {
        this.insertOrderEvent(orderId, type, userId, amount, new JSONObject());
    }

    public void insertOrderEvent(String orderId, String type, String userId, BigDecimal amount, JSONObject meta) {
        OrderEvent orderEvent = new OrderEvent();
        orderEvent.setId(idGenerator.next());
        orderEvent.setOrderId(orderId);
        orderEvent.setUserId(userId);
        orderEvent.setEventType(type);
        orderEvent.setAmount(amount);
        orderEvent.setMeta(meta);
        orderEvent.setCreatedAt(DatetimeUtils.now());
        jdbcAggregateTemplate.insert(orderEvent);
    }


    public List<?> organizeTimeline(String orderId) {
        Order order = orderService.getById(orderId);
        List<EventDto> events = orderEventRepository.findAllByOrderIdOrderByIdAsc(orderId)
                .stream().map(orderEvent -> new EventDto(orderEvent,
                        formatEvent(orderEvent, order))).toList();
        return events;
    }

    public List<OrderEvent> search(String eventType, Range range) {
        return orderEventRepository.findAllByEventTypeAndCreatedAtBetween(eventType, range.getStart(), range.getEnd());
    }

    public List<OrderEvent> search(String eventType, Range range, String userId) {
        return orderEventRepository.findAllByEventTypeAndUserIdAndCreatedAtBetween(eventType, userId, range.getStart(), range.getEnd());
    }


    @Data
    @AllArgsConstructor
    private static class EventDto {
        @JsonIgnore
        private OrderEvent event;
        private String message;

        public LocalDateTime getCreatedAt() {
            return event.getCreatedAt();
        }

    }

    private String formatEvent(OrderEvent orderEvent, Order order) {

        switch (orderEvent.getEventType()) {
            case "CREATED":
                return "买家%s(%s)创建了订单, 订单流水号：%s".formatted(order.getBuyerId(),
                        userCacheManager.get(order.getBuyerId()).getUser().getNickname(),
                        order.getId());
            case "CANCELED":
                return "%s取消了订单。".formatted(orderEvent.getUserId() == null ?
                        "因支付超时，自动" : "顾客");
            case "FIRST_SELLER_INFORMED":
                return "买家提醒确认收款".formatted(order.getFirstSellerId(),
                        userCacheManager.get(order.getFirstSellerId()).getUser().getNickname());
            case "BUYER_PAID":
                return "买家%s(%s)支付了货款".formatted(order.getBuyerId(),
                        userCacheManager.get(order.getBuyerId()).getUser().getNickname());
            case "SECOND_SELLER_INFORMED":
                return "经营店铺提醒确认收款".formatted(order.getFirstSellerId(),
                        userCacheManager.get(order.getFirstSellerId()).getUser().getNickname());
            case "FIRST_SELLER_PAID":
                return "经营店铺%s(%s)上交了扣除店铺利润后的货款".formatted(order.getFirstSellerId(),
                        userCacheManager.get(order.getFirstSellerId()).getUser().getNickname());
            case "SECOND_SELLER_PAID":
                return "管理店铺%s(%s)上交了扣除育成利润后的货款".formatted(order.getSecondSellerId(),
                        userCacheManager.get(order.getSecondSellerId()).getUser().getNickname());
            case "MADE_DELIVERY":
                return "总部已发货, 快递公司：%s, 运单号%s".formatted(
                        formatVendor(orderEvent.getMeta().get("deliveryVendorId").toString()),
                        order.getDeliveryNo());
            case "RECEIVED":
                return orderEvent.getUserId() == null ?"因超时，系统自动确认了收货":
                       "买家%s(%s)确认了收货".formatted(order.getBuyerId(),
                        userCacheManager.get(order.getBuyerId()).getUser().getNickname());
            default:
                return orderEvent.getEventType();
        }
    }

    private String formatVendor(String deliveryVendorId) {
        return Optional.ofNullable(dictionaryService.findByName("deliveryVendors")
                        .getKeyValues()
                        .get(deliveryVendorId))
                .map(item -> "%s(%s)".formatted(item.getText(), deliveryVendorId))
                .orElse(deliveryVendorId);
    }


}
